package com.tsfyun.scm.service.impl.finance;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tsfyun.common.base.enums.domain.InvoiceStatusEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.dto.finance.TaxCodeDTO;
import com.tsfyun.scm.entity.customer.Customer;
import com.tsfyun.scm.entity.finance.ImpSalesContractMember;
import com.tsfyun.scm.entity.finance.Invoice;
import com.tsfyun.scm.entity.finance.InvoiceMember;
import com.tsfyun.scm.entity.finance.TaxCodeName;
import com.tsfyun.scm.mapper.finance.InvoiceMemberMapper;
import com.tsfyun.scm.service.base.ISystemCacheService;
import com.tsfyun.scm.service.finance.IInvoiceMemberService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.service.finance.ITaxCodeNameService;
import com.tsfyun.scm.system.vo.TaxCodeBaseVO;
import com.tsfyun.scm.util.MaterielUtil;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.finance.ImpSalesContractMemberVO;
import com.tsfyun.scm.vo.finance.InvoiceMemberExcel;
import com.tsfyun.scm.vo.finance.InvoiceMemberVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 发票明细 服务实现类
 * </p>
 *

 * @since 2020-05-18
 */
@Service
public class InvoiceMemberServiceImpl extends ServiceImpl<InvoiceMember> implements IInvoiceMemberService {

    @Resource
    private Snowflake snowflake;

    @Autowired
    private ISystemCacheService systemCacheService;
    @Autowired
    private ITaxCodeNameService taxCodeNameService;
    @Autowired
    private InvoiceMemberMapper invoiceMemberMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAgentMember(Invoice invoice) {
        TaxCodeName taxCodeName = taxCodeNameService.defaultTaxCodeName(invoice.getBuyerId(),"代理进口服务费");
        InvoiceMember invoiceMember = new InvoiceMember();
        invoiceMember.setId(snowflake.nextId());
        invoiceMember.setRowNo(1);
        invoiceMember.setInvoiceId(invoice.getId());
        invoiceMember.setGoodsModel("代理进口服务费");
        invoiceMember.setGoodsName("代理进口服务费");
        invoiceMember.setGoodsBrand("代理进口服务费");
        invoiceMember.setQuantity(BigDecimal.ONE);
        invoiceMember.setUnitCode("007");
        invoiceMember.setUnitName("个");
        invoiceMember.setUnitPrice(invoice.getInvoiceVal());
        invoiceMember.setTotalPrice(invoice.getInvoiceVal());
        invoiceMember.setInvoiceName("代理进口服务费");
        invoiceMember.setTaxCode("");
        invoiceMember.setTaxCodeName("");
        invoiceMember.setIsFirst(Boolean.TRUE);
        if(Objects.nonNull(taxCodeName)){
            invoiceMember.setIsFirst(Boolean.FALSE);
            invoiceMember.setTaxCode(taxCodeName.getCode());
            invoiceMember.setTaxCodeName(taxCodeName.getCodeName());
            invoiceMember.setInvoiceName(taxCodeName.getInvoiceName());
        }else{
            invoice.setStatusId(InvoiceStatusEnum.WAIT_FINANCE_TAX.getCode());
        }
        super.saveNonNull(invoiceMember);
    }

    @Override
    public List<InvoiceMemberVO> getMembersByInvoiceId(Long invoiceId) {
        InvoiceMember invoiceMember = new InvoiceMember();
        invoiceMember.setInvoiceId(invoiceId);
        List<InvoiceMember> members = super.list(invoiceMember);
        if(CollUtil.isNotEmpty(members)){
            return beanMapper.mapAsList(members,InvoiceMemberVO.class).stream().sorted(Comparator.comparing(InvoiceMemberVO::getRowNo)).collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<InvoiceMember> saveMemberBySalesContractMembers(Invoice invoice,List<ImpSalesContractMemberVO> salesContractMembers) {
        List<InvoiceMember> members = Lists.newArrayListWithCapacity(salesContractMembers.size());
        Map<String,TaxCodeName> taxCodeNameMap = Maps.newLinkedHashMap();
        salesContractMembers.forEach(impSalesContractMember->{
            InvoiceMember invoiceMember = new InvoiceMember();
            invoiceMember.setId(snowflake.nextId());
            invoiceMember.setInvoiceId(invoice.getId());
            invoiceMember.setRowNo(impSalesContractMember.getRowNo());
            invoiceMember.setGoodsModel(MaterielUtil.formatGoodsModel(impSalesContractMember.getGoodsModel()));
            invoiceMember.setGoodsName(impSalesContractMember.getGoodsName());
            invoiceMember.setGoodsBrand(impSalesContractMember.getGoodsBrand());
            invoiceMember.setQuantity(impSalesContractMember.getQuantity());
            invoiceMember.setUnitCode(impSalesContractMember.getUnitCode());
            invoiceMember.setUnitName(impSalesContractMember.getUnitName());
            invoiceMember.setUnitPrice(impSalesContractMember.getUnitPrice());
            invoiceMember.setTotalPrice(impSalesContractMember.getTotalPrice());
            //匹配税收分类编码
            String key = invoice.getBuyerId()+invoiceMember.getGoodsName();
            TaxCodeName taxCodeName = taxCodeNameMap.get(key);
            if(Objects.isNull(taxCodeName)){
                taxCodeName = taxCodeNameService.defaultTaxCodeName(invoice.getBuyerId(),invoiceMember.getGoodsName());
                taxCodeNameMap.put(key,taxCodeName);
            }
            invoiceMember.setIsFirst(Boolean.TRUE);
            invoiceMember.setTaxCode("");
            invoiceMember.setTaxCodeName("");
            invoiceMember.setInvoiceName(impSalesContractMember.getGoodsName());
            if(Objects.isNull(taxCodeName)){//未匹配到编码
                //待财务确定编码
                invoice.setStatusId(InvoiceStatusEnum.WAIT_FINANCE_TAX.getCode());
            }else{
                invoiceMember.setTaxCode(taxCodeName.getCode());
                invoiceMember.setTaxCodeName(taxCodeName.getCodeName());
                invoiceMember.setInvoiceName(taxCodeName.getInvoiceName());
                invoiceMember.setIsFirst(!Objects.equals(taxCodeName.getCustomerId(),invoice.getBuyerId()));
            }
            members.add(invoiceMember);
        });
        return members;
    }

    @Override
    public List<InvoiceMemberExcel> findByInvoiceIds(List<Long> ids) {
        return invoiceMemberMapper.findByInvoiceIds(ids);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteByInvoiceId(Long invoiceId) {
        TsfWeekendSqls wheres = TsfWeekendSqls.<InvoiceMember>custom().andEqualTo(false,InvoiceMember::getInvoiceId,invoiceId);
        invoiceMemberMapper.deleteByExample(Example.builder(InvoiceMember.class).where(wheres).build());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveMemberTaxCode(List<TaxCodeDTO> members, Customer customer) {
        Map<String,TaxCodeBaseVO> tcMap = Maps.newLinkedHashMap();
        List<InvoiceMember> memberList = Lists.newArrayList();
        List<TaxCodeName> codeNameList = Lists.newArrayList();
        members.stream().forEach(dto ->{
            TaxCodeBaseVO taxCodeBaseVO = tcMap.get(dto.getTaxCode());
            if(Objects.isNull(taxCodeBaseVO)){
                taxCodeBaseVO = systemCacheService.getTaxCodeBaseByCode(dto.getTaxCode());
                tcMap.put(dto.getTaxCode(),taxCodeBaseVO);
            }
            TsfPreconditions.checkArgument(Objects.nonNull(taxCodeBaseVO),new ServiceException(String.format("税收分类编码【%s】错误",dto.getTaxCode())));
            InvoiceMember member = new InvoiceMember();
            member.setId(dto.getMid());
            member.setTaxCode(taxCodeBaseVO.getId());
            member.setTaxCodeName(taxCodeBaseVO.getShortName());
            member.setInvoiceName(dto.getInvoiceName());
            memberList.add(member);

            TaxCodeName codeName = new TaxCodeName();
            codeName.setId(snowflake.nextId());
            codeName.setCustomerId(customer.getId());
            codeName.setCustomerName(customer.getName());
            codeName.setName(dto.getGoodsName());
            codeName.setInvoiceName(dto.getInvoiceName());
            codeName.setCode(taxCodeBaseVO.getId());
            codeName.setCodeName(taxCodeBaseVO.getShortName());
            codeNameList.add(codeName);
        });
        // 更新发票明细税收编码
        invoiceMemberMapper.batchUpdateTax(memberList);
        // 更新税收编码对应表
        taxCodeNameService.batchInsert(codeNameList);
    }
}
